package core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import common.Sequence;
import common.Service;
import common.Servlet;
import common.Validate;
import dict.BcDict;
import dict.CbDict;
import dict.CommonDict;
import dict.TransactionDict;
import dicts.GlobalDict;
import dicts.PaymentDict;
import entities.TBank;
import entities.TBc;
import entities.TCb;
import entities.TMerchant;
import entities.TMs;
import entities.TSc;
import entities.TSm;
import entities.TTransaction;
import interfaces.IBankService;
import interfaces.IBcService;
import interfaces.ICbService;
import interfaces.IMerchantService;
import interfaces.IMsService;
import interfaces.IScService;
import interfaces.ISmService;
import interfaces.ITransactionService;
import net.sf.json.JSONObject;
import util.LogUtil;
import utils.DateUtil;
import utils.NumberUtil;
import utils.StringUtil;

public class Force extends Servlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public synchronized void process(HttpServletRequest request, HttpServletResponse response) throws Exception {

		System.out.println(DateUtil.format(new Date(), DateUtil.DATETIME) + " | 强制退款");

		// 初始化service
		IBankService bankService = (IBankService) Service.create(IBankService.class);
		ITransactionService transactionService = (ITransactionService) Service.create(ITransactionService.class);
		IMerchantService merchantService = (IMerchantService) Service.create(IMerchantService.class);
		IBcService bcService = (IBcService) Service.create(IBcService.class);
		ICbService cbService = (ICbService) Service.create(ICbService.class);
		IScService scService = (IScService) Service.create(IScService.class);
		ISmService smService = (ISmService) Service.create(ISmService.class);
		IMsService msService = (IMsService) Service.create(IMsService.class);

		Map<String, Object> paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
		JSONObject jsonResult = new JSONObject();

		// 初始化bean和属性
		TBank bank = new TBank();
		TMerchant merchant = new TMerchant();
		TTransaction transaction = new TTransaction();
		TBc bc = new TBc();
		TCb cb = new TCb();
		TSc sc = new TSc();
		TSm sm = new TSm();
		TMs ms = new TMs();

		// 验证系统
		if (GlobalDict.LINUX.equalsIgnoreCase(System.getProperty("os.name")) && !CommonDict.HOST.equals(request.getServerName())) {
			response.getWriter().print(Validate.result(TransactionDict.ILLAGEL_ACCESS, TransactionDict.MESSAGES.get(TransactionDict.ILLAGEL_ACCESS)));
			return;
		}

		// 校验参数 ( 名称,值,校验模式,边界 )
		List<Object[]> parameterList = Collections.synchronizedList(new ArrayList<Object[]>());
		parameterList.add(new Object[] { "bcNo", request.getParameter("bcNo"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "bcAmount", request.getParameter("bcAmount"), Validate.NOTEMPTY | Validate.ISNUMBER | Validate.EXCEEDNUMBER, 0, Integer.MAX_VALUE });
		parameterList.add(new Object[] { "bcRemark", request.getParameter("bcRemark"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });

		JSONObject validateResult = Validate.validate(parameterList);
		LogUtil.force(Validate.summary(parameterList));

		if (!StringUtil.isEmpty(validateResult)) {
			System.out.println ( validateResult.toString() ) ;
			response.getWriter().print(validateResult.toString());
			return;
		}

		// 入账存在状态
		try {
			bc = bcService.fetch(request.getParameter("bcNo"));
		} catch (Exception e) {
			response.getWriter().print(Validate.result(BcDict.BC_FETCH_EXCEPTION, BcDict.MESSAGES.get(BcDict.BC_FETCH_EXCEPTION)));
			return;
		}

		if (bc == null) {
			response.getWriter().print(Validate.result(BcDict.BC_NOT_EXIST, BcDict.MESSAGES.get(BcDict.BC_NOT_EXIST)));
			return;
		}

		if (!bc.getBcState().equals("1")) {
			response.getWriter().print(Validate.result(BcDict.BC_STATUS_EXCEPTION, BcDict.MESSAGES.get(BcDict.BC_STATUS_EXCEPTION)));
			return;
		}

		// 出账存在状态(是否之前还有未处理的退款项)
		try {
			paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
			paramMap.put("txnNo", bc.getTxnNo());
			paramMap.put("cbState", "0");
		} catch (Exception e) {
			response.getWriter().print(Validate.result(CbDict.CB_FETCH_EXCEPTION, CbDict.MESSAGES.get(CbDict.CB_FETCH_EXCEPTION)));
			return;
		}

		if (cbService.contain(paramMap)) {
			response.getWriter().print(Validate.result(CbDict.CB_ALREADY_EXIST, CbDict.MESSAGES.get(CbDict.CB_ALREADY_EXIST)));
			return;
		}

		// 查出对应交易
		try {
			transaction = transactionService.fetch(bc.getTxnNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_NOT_EXIST)));
			return;
		}
		if (transaction == null) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_NOT_EXIST)));
			return;
		}
		if (!transaction.getTxnState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_STATUS_EXCEPTION)));
			return;
		}

		// 查出对应商户
		try {
			merchant = merchantService.fetch(transaction.getMerNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_FETCH_EXCEPTION)));
			return;
		}
		if (merchant == null) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_NOT_EXIST)));
			return;
		}
		if (!merchant.getMerState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_STATUS_EXCEPTION)));
			return;
		}

		// 查出对应收单行
		try {
			bank = bankService.fetch(bc.getBnkNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.AGENCY_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_FETCH_EXCEPTION)));
			return;
		}
		if (bank == null) {
			response.getWriter().print(Validate.result(TransactionDict.AGENCY_CONFIGURATION_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_CONFIGURATION_EXCEPTION)));
			return;
		}
		if (!bank.getBnkState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.AGENCY_CLOSED, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_CLOSED)));
			return;
		}

		if (!bank.getBnkPart().equals("1") && new Double(request.getParameter("bcAmount")).doubleValue() != bc.getBcAmount().doubleValue()) {
			response.getWriter().print(Validate.result(TransactionDict.PART_REFUND_NOT_ACCEPT, TransactionDict.MESSAGES.get(TransactionDict.PART_REFUND_NOT_ACCEPT)));
			return;
		}
		
		// 计算退款金额
		try {
			ms.setMsAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(new Double(request.getParameter("bcAmount")), bc.getBcAmount(), 8)));
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.CALCULATE_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CALCULATE_EXCEPTION)));
			return;
		}

		// 退款金额大于剩余金额
		if (NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(new Double(request.getParameter("bcAmount")), bc.getBcAmount(), 4)) > transaction.getTxnRemain()) {
			response.getWriter().print(Validate.result(TransactionDict.REFUND_AMOUNT_GREATER_THAN_REMAINING, TransactionDict.MESSAGES.get(TransactionDict.REFUND_AMOUNT_GREATER_THAN_REMAINING)));
			return;
		}

		// 把退款记录进行保存并清算而不上送收单行
		cb.setCbNo(Sequence.cbSequence());
		cb.setCrdNo(bc.getCrdNo());
		cb.setBnkNo(bank.getBnkNo());
		cb.setTxnNo(bc.getTxnNo());
		cb.setCbType(PaymentDict.CB_REFUND);
		cb.setCbOrder(bc.getBcOrder());
		cb.setCbCur(CommonDict.CUR);
		cb.setCbAmount(new Double(request.getParameter("bcAmount")));
		cb.setCbMoney(cb.getCbAmount());
		cb.setCbRef(bc.getBcRef());
		cb.setCbCard(bc.getBcCard());
		cb.setCbTime(bc.getBcTime());
		cb.setCbMark("0000");
		cb.setCbInfo("force refund");
		cb.setCbCode(CbDict.CB_SUCCESS);
		cb.setCbMessage(CbDict.MESSAGES.get(CbDict.CB_SUCCESS));
		cb.setCbState("1");
		cb.setCbDate(new Date());
		cb.setCbCstate("1");
		cb.setCbCdate(new Date(0L));
		cb.setCbRemark(request.getParameter("bcRemark"));
		cbService.persist(cb);

		ms.setMsNo(Sequence.msSequence());
		ms.setMerNo(merchant.getMerNo());
		ms.setTxnNo(transaction.getTxnNo());
		ms.setMsType(PaymentDict.MS_REFUND);
		ms.setMsAmount(ms.getMsAmount());
		ms.setMsState("1");
		ms.setMsDate(new Date());
		ms.setMsRemark(cb.getCbRemark());
		msService.persist(ms);

		sc.setScNo(Sequence.scSequence());
		sc.setCrdNo(transaction.getCrdNo());
		sc.setTxnNo(transaction.getTxnNo());
		sc.setScType(PaymentDict.SC_DEALAGE);
		sc.setScAmount(ms.getMsAmount());
		sc.setScState("1");
		sc.setScDate(new Date());
		scService.persist(sc);

		sc.setScNo(Sequence.scSequence());
		sc.setCrdNo(transaction.getCrdNo());
		sc.setTxnNo(transaction.getTxnNo());
		sc.setScType(PaymentDict.SC_MARKUP);
		sc.setScAmount(NumberUtil.sub(cb.getCbAmount(), ms.getMsAmount()));
		sc.setScState("1");
		sc.setScDate(new Date());
		scService.persist(sc);
		
		transaction.setTxnRemain(NumberUtil.sub(transaction.getTxnRemain(), ms.getMsAmount()));
		if (transaction.getTxnRemain() == 0) {
			transaction.setTxnLogic("1");
		}
		transaction.setTxnRefund("1");
		transactionService.persist(transaction);

		// 时间小于24小时,并且商户配置为退还手续费
		if (merchant.getMerRefunding().equals("1") && new Date().getTime() - transaction.getTxnDate().getTime() < GlobalDict.DAY) {
			try {
				paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
				paramMap.put("txnNo", StringUtil.split(request.getParameter("transaction")));
				paramMap.put("msType", PaymentDict.MS_POUNDAGE);
				ms = msService.single(paramMap);
			} catch (Exception e) {
				response.getWriter().print(Validate.result(TransactionDict.MS_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MS_FETCH_EXCEPTION)));
				return;
			}

			if (ms != null) {
				sm.setSmNo(Sequence.smSequence());
				sm.setMerNo(transaction.getMerNo());
				sm.setTxnNo(transaction.getTxnNo());
				sm.setSmType(PaymentDict.SM_POUNDAGE);
				sm.setSmAmount(ms.getMsAmount());
				sm.setSmState("1");
				sm.setSmDate(new Date());
				smService.persist(sm);
			}
		}

		jsonResult.put("code", cb.getCbCode());
		jsonResult.put("message", cb.getCbMessage());

		response.getWriter().print(jsonResult.toString());
		return;

	}
}
